<template>
  <div class="container">
    <template v-if="loading">
      <div class="loading">
        Loading
      </div>
    </template>
    <template v-else>
      <div class="canvas" ref="canvas"></div>
      <div id="js-properties-panel" class="panel"></div>
    </template>
  </div>
</template>

<script>
import axios from 'axios'
import BpmnModeler from 'bpmn-js/lib/Modeler'
// 引入一个本地的xml字符串，若是没有获取到后台的数据则用它
import { xmlStr } from '@/mock/xmlStr'

// 使用右侧属性栏
import propertiesPanelModule from 'bpmn-js-properties-panel'
import propertiesProviderModule from 'bpmn-js-properties-panel/lib/provider/camunda'
import camundaModdleDescriptor from 'camunda-bpmn-moddle/resources/camunda'
export default {
  data () {
    return {
      bpmnModeler: null, // bpmn 建模器
      container: null,
      canvas: null,
      loading: true,
      xmlUrl: '',
      defaultXmlStr: xmlStr
    }
  },
  mounted() {
    this.init()
  },
  methods: {
    async init () {
      this.loading = true
      this.xmlUrl = await this.getXmlUrl()
      console.log(this.xmlUrl)
      this.loading = false
      // 等待 DOM 更新之后再对工作流进行初始化
      this.$nextTick(() => {
        this.initBpmn()
      })
    },
    // 该方法模拟请求后台获取 bpmn 文件
    getXmlUrl () {
      return new Promise(resolve => {
        setTimeout(() => {
          const url = 'https://hexo-blog-1256114407.cos.ap-shenzhen-fsi.myqcloud.com/bpmnMock.bpmn'
          resolve(url)
        }, 1000)
      })
    },
    initBpmn () {
      // 获取canvas的dom节点
      const canvas = this.$refs.canvas
      // 建模
      this.bpmnModeler = new BpmnModeler({
        container: canvas,
        // 添加控制板
        propertiesPanel: {
          parent: '#js-properties-panel'
        },
        additionalModules: [
          // 右边的属性栏
          propertiesProviderModule,
          propertiesPanelModule
        ],
        moddleExtensions: {
          camunda: camundaModdleDescriptor
        }
      })
      this.createNewDiagram()
    },
    async createNewDiagram () {
      const that = this
      let bpmnXmlStr = ''
      if (this.xmlUrl === '') { // 若是后台没有数据则使用默认的一个 xml
        bpmnXmlStr = this.defaultXmlStr
        this.transformCanvas(bpmnXmlStr)
      } else {
        let res = await axios({
          method: 'get',
          timeout: 120000,
          url: that.xmlUrl,
          headers: { 'Content-Type': 'multipart/form-data' }
        })
        console.log(res)
        bpmnXmlStr = res['data']
        this.transformCanvas(bpmnXmlStr)
      }
    },
    transformCanvas (bpmnXmlStr) {
      // 将字符串转换成图显示出来
      try {
        const result = this.bpmnModeler.importXML(bpmnXmlStr)
        const { warnings } = result
        console.log(warnings)
        this.success()
        // 让图能自适应屏幕
        var canvas = this.bpmnModeler.get('canvas')
        canvas.zoom('fit-viewport')
      } catch (err) {
        console.log(err.message, err.warnings)
      }
    },
    success () {
      console.log('创建成功')
      this.addBpmnListener()
    },
    // 添加绑定事件
    addBpmnListener () {
      // 给图绑定事件，当图有发生改变的时候就会触发这个事件
      this.bpmnModeler.on('commandStack.changed', () => {
        this.saveDiagram((err, xml) => {
          console.log(xml) // 这里获取到的就是最新的 xml 信息
        })
      })
    },
    // 下载为 bpmn 格式，done 是个函数，调用的时候传入的
    saveDiagram (done) {
      // 把传入的 done 再传给 bpmn 原型的 saveXML 函数调用
      this.bpmnModeler.saveXML({ format: true }, (err, xml) => {
        done(err, xml)
      })
    }
  }
}
</script>

<style scoped>
.container {
  position: relative;
  width: 100%;
  height: 100%;
}
.canvas {
  width: 100%;
  height: 100%;
}
.panel {
  position: absolute;
  top: 0;
  right: 0;
  width: 300px;
}
</style>